Skip to content

[CALCITE-7646] CorrelateProjectExtractor does not handle nested field accesses cor0.field0.field1#5086

Open
mihaibudiu wants to merge 3 commits into
apache:mainfrom
mihaibudiu:issue7646
Open

[CALCITE-7646] CorrelateProjectExtractor does not handle nested field accesses cor0.field0.field1#5086
mihaibudiu wants to merge 3 commits into
apache:mainfrom
mihaibudiu:issue7646

Conversation

@mihaibudiu

Copy link
Copy Markdown
Contributor

Jira Link

CALCITE-7646

Changes Proposed

These changes make the helper class slightly more capable, enabling more programs to be decorrelated.

@mihaibudiu

Copy link
Copy Markdown
Contributor Author

@zabetak according to git blame you wrote most of this code, so I took the liberty to request your review.

@mihaibudiu

Copy link
Copy Markdown
Contributor Author

I think the CI failure is transient, the tests pass locally.

@xuzifu666

xuzifu666 commented Jul 7, 2026

Copy link
Copy Markdown
Member

I think the CI failure is transient, the tests pass locally.

There shouldn't be any problems. I re-trigger sonar CI to double-check.

@mihaibudiu

Copy link
Copy Markdown
Contributor Author

The fact that I requested a review from @zabetak should not deter anyone else from reviewing this PR. I think it's a genuine improvement which will help our decorrelator handle more queries.

@iwanttobepowerful

Copy link
Copy Markdown
Contributor

Would it also be possible to add a few SQL-based test cases to QuidemTest?

@mihaibudiu

Copy link
Copy Markdown
Contributor Author

Sure, I will do that, but the results should not change, just the nature of the plan

@xuzifu666 xuzifu666 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my view the overall implementation is ok and meets the objectives. Apart from suggesting the addition of QuidemTest, I have left two comments for your reference.

Comment thread core/src/main/java/org/apache/calcite/sql2rel/CorrelateProjectExtractor.java Outdated
@mihaibudiu

Copy link
Copy Markdown
Contributor Author

Would it also be possible to add a few SQL-based test cases to QuidemTest?

I have added a few quidem tests covering both decorrelators.

@mihaibudiu

Copy link
Copy Markdown
Contributor Author

Interestingly, Claude actually found a (related) bug in the original optimization, which forgot to preserve fields NOT moved into requiredColumns. Several test cases cover these failures. I haven't filed a separate issue since there is common code between this "improvement" and the bug fix itself. As a consequence of this fix several plans have changed, but they are equivalent and always better.

@zabetak zabetak left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM! Left some small comments/suggestions but nothing major.

if (node instanceof RexFieldAccess) {
RexFieldAccess access = (RexFieldAccess) node;
if (access.getReferenceExpr() instanceof RexCorrelVariable) {
RexCorrelVariable var = (RexCorrelVariable) access.getReferenceExpr();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var is a reserved keyword in JDK 10+ so to avoid any potential confusion I think its worth addressing this minor sonar warning.

List<RexNode> callsWithCorrelationOverLeft = new ArrayList<>();
for (RexNode callInRight : callsWithCorrelationInRight) {
callsWithCorrelationOverLeft.add(replaceCorrelationsWithInputRef(callInRight, builder));
if (isDirectFieldAccess(callInRight, correlate.getCorrelationId())) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How important is to have this condition? I understand that it tries to block "trivial" correlated expressions from generating redundant column references but it shouldn't lead to incorrect plans.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually this is the bug that leads to the two crashes highlighted in some of the tests.
You need to put the field in the list of required columns.

Comment thread core/src/test/resources/sql/struct.iq Outdated
# 4 test cases for [CALCITE-7646] CorrelateProjectExtractor
# does not handle nested field accesses cor0.field0.field1.

# All queries use LATERAL, which converts directly to a Correlate.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the queries make use of lateral they fit better in the lateral.iq file.

Comment thread core/src/test/resources/sql/struct.iq Outdated
!use scott

# Before the fix planning failes with
# "Mappings$NoElementException: source #0 has no target in mapping".

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem/failure (along with stacktrace information) are much more useful in the Jira description than in comments in the code. Users encountering a problem will first search on Google/Jira before digging into the code.

For reviewers its also easier to understand the context of the work by reading the problem description first.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will move the error descriptions in Jira and delete them from the comments

Comment thread core/src/test/resources/sql/struct.iq Outdated
Comment on lines +374 to +384
!if (use_new_decorr) {
EnumerableCalc(expr#0..3=[{inputs}], expr#4=['SALES':VARCHAR(14)], expr#5=[=($t1, $t4)], DD=[$t2], X=[$t3], $condition=[$t5])
EnumerableCorrelate(correlation=[$cor1], joinType=[inner], requiredColumns=[{0}])
EnumerableCalc(expr#0..2=[{inputs}], proj#0..1=[{exprs}])
EnumerableTableScan(table=[[scott, DEPT]])
EnumerableCalc(expr#0=[{inputs}], expr#1=[$cor1], expr#2=[$t1.DEPTNO], DD=[$t2], X=[$t0])
EnumerableUncollect
EnumerableCalc(expr#0=[{inputs}], expr#1=[$cor1], expr#2=[$t1.DEPTNO], expr#3=[100], expr#4=[+($t2, $t3)], expr#5=[ARRAY($t4)], EXPR$0=[$t5])
EnumerableValues(tuples=[[{ 0 }]])
!plan
!}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new decorrelator is not using the CorrelateProjectExtractor so to some extend this test is unrelated to the fix and somewhat redundant. Is there something specific that we want to check in the plan?

Comment thread core/src/test/resources/sql/struct.iq Outdated
Comment on lines +363 to +372
!if (use_old_decorr) {
EnumerableCalc(expr#0..3=[{inputs}], DD=[$t2], X=[$t3])
EnumerableCorrelate(correlation=[$cor1], joinType=[inner], requiredColumns=[{0, 1}])
EnumerableCalc(expr#0..2=[{inputs}], expr#3=[100], expr#4=[+($t0, $t3)], expr#5=[ARRAY($t4)], expr#6=['SALES':VARCHAR(14)], expr#7=[=($t1, $t6)], DEPTNO=[$t0], $f3=[$t5], $condition=[$t7])
EnumerableTableScan(table=[[scott, DEPT]])
EnumerableCalc(expr#0=[{inputs}], expr#1=[$cor1], expr#2=[$t1.DEPTNO], DD=[$t2], X=[$t0])
EnumerableUncollect
EnumerableCalc(expr#0=[{inputs}], expr#1=[$cor1], expr#2=[$t1.$f3], EXPR$0=[$t2])
EnumerableValues(tuples=[[{ 0 }]])
!plan

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart from the fact that the query runs (does not crash) and produces correct results what do we want to assert/verify in the query plan?
If we don't really care about the query plan then we should skip it. If there is something that we need to validate then an extra comment would be helpful.

Comment thread core/src/test/resources/sql/struct.iq Outdated

# EnumerableRules.ENUMERABLE_CORRELATE_RULE is removed so that this test
# fails if the plan cannot be fully decorrelated.
!set planner-rules "-EnumerableRules.ENUMERABLE_CORRELATE_RULE"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice idea for ensuring that a plan is fully decorrelated although such test would fit better in RelDecorrelatorTest where it would be more readable.

… accesses cor0.field0.field1

Signed-off-by: Mihai Budiu <mbudiu@feldera.com>
Signed-off-by: Mihai Budiu <mbudiu@feldera.com>
Signed-off-by: Mihai Budiu <mbudiu@feldera.com>
@mihaibudiu

Copy link
Copy Markdown
Contributor Author

@zabetak I have temporarily pushed the changes requested by your review as a second commit, for you to check.
I plan to squash and merge eventually.

@mihaibudiu mihaibudiu added the LGTM-will-merge-soon Overall PR looks OK. Only minor things left. label Jul 14, 2026
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

LGTM-will-merge-soon Overall PR looks OK. Only minor things left.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants